package de.unikoblenz.west.csxpoi;

import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Looper;

/**
 * The location thread, which listens for location updates from GPS, cell
 * towers, or Wifi and provides the most accurate current location.
 */
public class LocationThread extends Thread {

	/**
	 * the looper for the location updates
	 */
	private Looper mLooper;

	/**
	 * the status of GPS (initially unavailable)
	 */
	private int mGPSStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;

	/**
	 * the most accurate current location
	 */
	private Location mLocation;

	/**
	 * the minimum time in milliseconds between location updates
	 */
	public static final long mMinTime = 1000;

	/**
	 * the minimum distance in meters between location updates
	 */
	public static final float mMinDistance = 1;

	/**
	 * the location manager to request location updates from
	 */
	private LocationManager mLocationManager;

	/**
	 * the location listener listening for location updates
	 */
	private final LocationListener mLocationListener = new LocationListener() {

		/**
		 * Called when the location changed.
		 */
		public void onLocationChanged(Location location) {
			if (location != null) {

				// Use GPS location unless not available, then network:

				if (location.getProvider().equals(LocationManager.GPS_PROVIDER)
						|| mGPSStatus != LocationProvider.AVAILABLE) {
					mLocation = location;
				}
			} else {
				mLocation = null;
			}
		}

		/**
		 * Called when the location provider is disabled.
		 */
		public void onProviderDisabled(String provider) {
			return;
		}

		/**
		 * Called when the location provider is enabled.
		 */
		public void onProviderEnabled(String provider) {
			return;
		}

		/**
		 * Called when the status of the location provider changes.
		 */
		public void onStatusChanged(String provider, int status, Bundle extras) {
			mGPSStatus = status;
		}
	};

	/**
	 * Called when the location thread is created.
	 * 
	 * @param locationManager
	 *            the location manager to request location updates from
	 */
	LocationThread(LocationManager locationManager) {
		super();
		mLocationManager = locationManager;
		mLocation = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		
	}

	/**
	 * Gets the most accurate current location
	 * 
	 * @return the most accurate current location
	 */
	public Location getLocation() {
		return mLocation;
	}

	/**
	 * Starts the location thread.
	 */
	@Override
	public void run() {

		Looper.prepare();
		mLooper = Looper.myLooper();

		// Request both network and GPS updates:

		mLocationManager.requestLocationUpdates(
				LocationManager.NETWORK_PROVIDER, mMinTime, mMinDistance,
				mLocationListener, mLooper);
		mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				mMinTime, mMinDistance, mLocationListener, mLooper);

		Looper.loop();
	}

	/**
	 * Stops the location thread.
	 */
	public void requestExitAndWait() {

		mLocationManager.removeUpdates(mLocationListener);

		mLooper.quit();
		mLooper = null;

		try {
			join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}
